{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "8581c098-12ba-4be5-bf04-c89682c558c5",
   "metadata": {},
   "source": [
    "#### 基础索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "e08d53aa-a37a-444c-9b23-94e91aaf5fa0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "# 一维数组 看作：向量\n",
    "# 一般用小写字母表示\n",
    "a = np.arange(10)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "0134b4c6-2df2-4d20-b5a0-48d493ab52f7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  1,  2,  3,  4],\n",
       "       [ 5,  6,  7,  8,  9],\n",
       "       [10, 11, 12, 13, 14],\n",
       "       [15, 16, 17, 18, 19]])"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 二维数组 看作：矩阵\n",
    "# 一般用大写字母表示\n",
    "A = np.arange(20).reshape(4,5)\n",
    "A"
   ]
  },
  {
   "cell_type": "raw",
   "id": "87895655-fd49-4e4a-8cbd-a1075839c808",
   "metadata": {},
   "source": [
    "#### 一维数组通过索引取值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "6a91c6ff-3209-4601-b562-c8bccfcf2c16",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 9\n"
     ]
    }
   ],
   "source": [
    "# 单个索引,支持负索引（从右往左数）\n",
    "print(a[0],a[-1])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "30232568-9cf6-47c7-9278-e3bd698e2d55",
   "metadata": {},
   "source": [
    "#### 切片索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "63e84c81-58d1-4ef7-9ce2-1982762b94d4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 2 3]\n",
      "[0 1 2]\n",
      "[0 2 4 6 8]\n",
      "[9 8 7 6 5 4 3 2 1 0]\n",
      "[0 2 4 6] [9 8 7 6 5 4 3]\n"
     ]
    }
   ],
   "source": [
    "#  a[start:stop:step] 可以省略 start / stop / step\n",
    "print(a[1:4])   # 从索引1到3（不含4）\n",
    "print(a[:3])    # 省略开头\n",
    "print(a[::2])   # 步长2\n",
    "print(a[::-1])  # 反向取值\n",
    "print(a[0:8:2],a[:2:-1])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a6d09cde-ed28-481d-b1df-639a46913799",
   "metadata": {},
   "source": [
    "#### 布尔索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "17dad2a6-ac23-4c8b-aa57-e0a530f83012",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[array([ True,  True, False,  True, False,  True, False,  True, False,\n",
      "        True])]\n"
     ]
    }
   ],
   "source": [
    "# 传入一个和数组等长的布尔数组, True 的位置保留，False 的位置丢弃。\n",
    "mask = np.array([True,True,False,True,False,True,False,True,False,True])\n",
    "randomArray = np.random.randint(1,10,10)\n",
    "print([mask])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "10d2561e-a503-48a0-8109-f144000f9b56",
   "metadata": {},
   "source": [
    "#### 条件索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "a11fe71f-2099-4795-ae8c-0333e4ec5f82",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[7 7 7 8]\n"
     ]
    }
   ],
   "source": [
    "# 使用条件表达式直接生成布尔数组。常用于过滤\n",
    "print(randomArray[randomArray>5])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c598e935-f1df-4e6e-b733-abfc5a386bb9",
   "metadata": {},
   "source": [
    "#### 花式索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "4920d6b9-46f0-4845-a186-e911dff054d8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[3 5 4]\n",
      "[4 4 4 4 1]\n"
     ]
    }
   ],
   "source": [
    "# 用整数列表或数组指定任意索引位置。可重复、可打乱顺序\n",
    "print(randomArray[[1,2,3]])\n",
    "print(randomArray[np.random.randint(3,8,5)])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0bd8e5aa-8512-41c4-a0b8-271205f255d5",
   "metadata": {},
   "source": [
    "#### 索引混合使用"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "d4e86545-271d-4c92-b1c8-61cddb5f0f49",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[7 4 1 4 5]\n"
     ]
    }
   ],
   "source": [
    "# 可以组合花式索引、切片、条件索引一起用。\n",
    "print(randomArray[[2,3,4,5,6]][::-1])      # 先花式索引，再切片反转"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "05538eb6-8846-45e8-8463-6942d9a5e3c4",
   "metadata": {},
   "source": [
    "#### 通过 take() 方法索引\n",
    "```python\n",
    "np.take(a, indices, axis=None, out=None, mode='raise')\n",
    "```\n",
    "- a: 输入数组。\n",
    "- indices: 要取的元素的索引，可以是单个整数或整数数组。\n",
    "- axis: 指定沿哪个轴取值。如果是 None，会先把 a 展平（变成一维），再取元素。\n",
    "- out: 可选参数，把结果写到指定数组里（需要形状匹配）。\n",
    "- mode: 指定索引超出范围时的行为：\n",
    "    - 'raise'（默认）：超出范围报错。\n",
    "    - 'wrap'：把索引按数组长度取模（循环取值）。\n",
    "    - 'clip'：把超出范围的索引夹在合法范围内。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "64191e91-0c6c-471f-b664-8aae54138516",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([3, 5])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 与花式索引类似，但是函数调用形式。可以配合 mode='clip' 等参数，控制越界行为。\n",
    "np.take(np.arange(10),[3,5])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "10cd7c5c-d4be-403c-b98f-1eaf36f88d39",
   "metadata": {},
   "source": [
    "#### 通过 item()取单值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "de4e929b-2d1d-49ba-b913-14c1eda37152",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0 1 2 3]\n",
      " [4 5 6 7]]\n",
      "5\n",
      "4\n"
     ]
    }
   ],
   "source": [
    "# 用 item() 取指定位置的扁平化索引\n",
    "A = np.arange(8).reshape(2,4)\n",
    "print(A)\n",
    "print(A.item(5))     # 根据扁平化索引取值\n",
    "print(A.item(1,0))   # 多维索引，等价于 a[1, 0]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7629c89e-8cee-4220-ad2e-3dce39391406",
   "metadata": {},
   "source": [
    "#### 通过 item()取单值/ 普通索引设值\n",
    "> itemset() 给单值赋值（Numpy2.0中已移出）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "4b36e16f-4993-420c-b14d-ee9b0d064886",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "原始数组 A:\n",
      " [[0 1 2 3]\n",
      " [4 5 6 7]]\n",
      "5\n",
      "4\n"
     ]
    }
   ],
   "source": [
    "# 1️⃣ 用 item() 取单个元素\n",
    "A = np.arange(8).reshape(2, 4)\n",
    "print(\"原始数组 A:\\n\", A)\n",
    "print(A.item(5))       # 根据扁平化索引取值 -> 5\n",
    "print(A.item(1, 0))    # 多维索引，等价于 A[1, 0] -> 4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "d3a77a63-69ed-4ad5-926e-456fc4e1d760",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "[[ 0 99  2  3]\n",
      " [ 4  5  6  7]]\n"
     ]
    }
   ],
   "source": [
    "# 2️⃣ 单元素普通索引取值/赋值\n",
    "A = np.arange(8).reshape(2, 4)\n",
    "print(A[0, 1])         # 取第0行第1列 -> 1\n",
    "A[0, 1] = 99           # 修改第0行第1列\n",
    "print(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "558cf5c3-847a-475d-8b66-3de4e96c4dec",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0 1 2 3]\n",
      " [4 5 6 7]]\n",
      "[[1 2]\n",
      " [5 6]]\n",
      "[[ 0  1  2  3]\n",
      " [22 22 22 22]]\n",
      "[[ 0  1 -1 -1]\n",
      " [22 22 -1 -1]]\n"
     ]
    }
   ],
   "source": [
    "# 3️⃣ 行或列切片\n",
    "A = np.arange(8).reshape(2, 4)\n",
    "print(A[0:2])          # 取前两行\n",
    "print(A[:, 1:3])       # 取所有行，第1~2列\n",
    "\n",
    "A[1:2] = 22            # 把第1行所有列赋值为22\n",
    "print(A)\n",
    "\n",
    "A[:, 2:4] = -1         # 把第2~3列所有行赋值为-1\n",
    "print(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "b10657f0-439b-4862-8908-c09ce8fb86f2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 7]\n",
      "[[ 0 -1  2  3]\n",
      " [ 4  5  6 -1]]\n",
      "[[ 0 -1  2  3]\n",
      " [ 4  5  6 -1]]\n",
      "[[0 2]\n",
      " [4 6]]\n"
     ]
    }
   ],
   "source": [
    "# 4️⃣ 花式索引（取指定元素）\n",
    "A = np.arange(8).reshape(2, 4)\n",
    "print(A[[0, 1], [1, 3]])   # 取 (0,1) 和 (1,3) -> [99, -1]\n",
    "A[[0, 1], [1, 3]] = -1     # 同时修改多个元素\n",
    "print(A)\n",
    "\n",
    "print(A[[0, 1]])           # 取第0行和第1行\n",
    "print(A[:, [0, 2]])        # 取第0列和第2列"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "e35f0af3-3714-48e3-8bdb-e2464d2e2a12",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[6 7]\n",
      "[[  0   1   2   3]\n",
      " [  4   5 100 100]]\n"
     ]
    }
   ],
   "source": [
    "# 5️⃣ 布尔索引\n",
    "A = np.arange(8).reshape(2, 4)\n",
    "mask = A > 5\n",
    "print(A[mask])             # 取所有 >5 的元素\n",
    "A[mask] = 100              # 修改所有 >5 的元素\n",
    "print(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "e58654ed-3212-4eca-ac7f-4cb6ce247dfa",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 3]\n",
      " [5 7]]\n",
      "[[0 0 2 0]\n",
      " [4 0 6 0]]\n"
     ]
    }
   ],
   "source": [
    "# 6️⃣ 混合索引\n",
    "A = np.arange(8).reshape(2, 4)\n",
    "print(A[0:2, [1, 3]])      # 前两行，第1和第3列\n",
    "A[0:2, [1, 3]] = 0          # 批量修改指定元素\n",
    "print(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "f8aacbd7-376c-4ab2-821d-c9002babe0b1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0 1 2 3]\n",
      " [4 5 6 7]]\n"
     ]
    }
   ],
   "source": [
    "# 7️⃣ 空切片（不会修改数组）\n",
    "A = np.arange(8).reshape(2, 4)\n",
    "A[1:1] = 999               # 切片为空，不修改数组\n",
    "print(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "0ea65935-3043-4a00-88b4-26801be4e76a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[2 2 2 2]\n",
      " [2 2 2 2]]\n",
      "[[ 2  2 -1  2]\n",
      " [ 2  2 -1  2]]\n"
     ]
    }
   ],
   "source": [
    "# 8️⃣ 广播赋值\n",
    "A = np.arange(8).reshape(2, 4)\n",
    "A[0:2] = 2                  # 前两行所有元素赋值为2\n",
    "print(A)\n",
    "\n",
    "A[:, 2] = -1                # 第2列所有行赋值为-1\n",
    "print(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "26b63ab5-260c-4534-9e0c-a431ad750ce7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[  0   1   2 123]\n",
      " [  4   5   6   7]]\n"
     ]
    }
   ],
   "source": [
    "# 9️⃣ 扁平化索引赋值（替代 itemset）\n",
    "A = np.arange(8).reshape(2, 4)\n",
    "A.ravel()[3] = 123           # 修改扁平化索引第3个元素\n",
    "print(A)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7555bb72-f2ec-4606-9958-ec85f250b86a",
   "metadata": {},
   "source": [
    "#### flat 迭代器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "3e84baad-bf9d-4bbe-812c-351d479ea472",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4\n",
      "0\n",
      "0 1 2 3 4 5 "
     ]
    }
   ],
   "source": [
    "# 可以把任意形状的 NumPy 数组当成一维数组来访问\n",
    "# flat 返回的是 可迭代对象，而不是新的数组副本（或视图）\n",
    "# 可以通过索引访问单个元素，也可以用它来迭代整个数组。\n",
    "A = np.arange(6).reshape(2,3)\n",
    "print(A.flat[4])   # 扁平化索引 4 -> 4\n",
    "print(A.flat[0])   # 扁平化索引 0 -> 0\n",
    "\n",
    "# 遍历数组\n",
    "for x in A.flat:\n",
    "    print(x, end=' ')\n",
    "\n",
    "# 只能修改单个元素，如果像切片一样赋值多个元素，flat 不支持 \n",
    "A.flat[2] = 99\n",
    "\n",
    "# 可以使用 ravel扁平化赋值\n",
    "A.ravel()[0:3] = [10, 20, 30]   # 扁平化赋值"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c9f03255-8332-4c69-b9c8-e6ddab10a7c6",
   "metadata": {},
   "source": [
    "#### take_along_axis() 高级索引\n",
    "适合按索引数组对某个轴进行取值，很多时候用它比普通切片更灵活\n",
    "`np.take_along_axis(arr, indices, axis)`\n",
    "- arr：输入数组\n",
    "- indices：索引数组，和 arr 的形状必须兼容\n",
    "- axis：沿着哪一轴取值\n",
    "    - axis=0：沿着**第0维（行）**操作 → “在列方向上变化”\n",
    "    - axis=1：沿着**第1维（列）**操作 → “在行方向上变化”\n",
    "    - axis=2：沿着**第2维（深度）**操作 → “在层方向上变化”\n",
    "\n",
    "**特点：take_along_axis 可以根据 指定索引数组 按轴取值，返回的结果与索引数组形状一致。**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "b096bede-1d47-476a-b2d3-1496f8df77fa",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[49 96  2]\n",
      " [26  9 10]]\n"
     ]
    }
   ],
   "source": [
    "A = np.random.randint(1,100,(2,3))\n",
    "print(A)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "5f532d5c-4e37-48d8-837a-929b2f1ebfae",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[49 96]\n",
      " [26 10]]\n"
     ]
    }
   ],
   "source": [
    "indices=np.array([\n",
    "    [0,1],\n",
    "    [0,2]\n",
    "])\n",
    "result=np.take_along_axis(A,indices,axis=1)\n",
    "\n",
    "print(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "dc79aaed-50f1-47a9-a049-8413591e9f4a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[26, 96, 10]])"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "indices = np.array([[1,0,1]])\n",
    "np.take_along_axis(A,indices,0)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1a610862-a26d-4972-bb43-77ea4647ed52",
   "metadata": {},
   "source": [
    "#####\n",
    "| 函数                | `axis=0` 含义 | `axis=1` 含义 |\n",
    "| ----------------- | ----------- | ----------- |\n",
    "| `sum` / `mean`    | 每列求和（跨行）    | 每行求和（跨列）    |\n",
    "| `argmax`          | 每列找最大值（跨行）  | 每行找最大值（跨列）  |\n",
    "| `take_along_axis` | 每列取值（跨行）    | 每行取值（跨列）    |\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "d9aa53c7-e674-4ae5-a8e8-72a9b7b4c039",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[49 96  2]\n",
      " [26  9 10]]\n",
      "[0 0 1]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([[0, 0, 1]])"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "indices = np.argmax(A,axis=0)\n",
    "print(A)\n",
    "print(indices)\n",
    "indices[np.newaxis,:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "65974a85-7889-4e95-9752-becb3dc33c88",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[0, 0, 1]]])"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 直接扩展维度，外围整体包裹\n",
    "indices[None,None,:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "2e8b39d2-8f6c-4ea0-bf26-03125a97540c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[[49, 96,  2]]],\n",
       "\n",
       "\n",
       "       [[[26,  9, 10]]]])"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 对内部元素进行维度扩展，内部item包裹\n",
    "A[:,None,None]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "4da5030a-7dfd-4368-bf78-8a05462efd15",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[[49, 96,  2]],\n",
       "\n",
       "        [[26,  9, 10]]]])"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A[None,:,None]"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
